package org.ptkparty.client.view.stats;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.ptkparty.client.activity.StatsActivity;
import org.ptkparty.client.model.UserProxy;
import org.ptkparty.client.ui.UserSelectionCellListView;
import org.ptkparty.shared.dto.GameDto;
import org.ptkparty.shared.dto.ResultDto;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor.Path;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.LegendPosition;
import com.google.gwt.visualization.client.visualizations.ColumnChart;
import com.google.gwt.visualization.client.visualizations.LineChart;
import com.google.gwt.visualization.client.visualizations.LineChart.Options;

public class StatsView extends Composite {

	private static StatsViewUiBinder uiBinder = GWT.create(StatsViewUiBinder.class);

	interface StatsViewUiBinder extends UiBinder<Widget, StatsView> {
	}

	private ListDataProvider<UserProxy> provider;
	private StatsActivity activity;
	private Map<String, String> userToId = new HashMap<String, String>();
	private LineChart lineChart = null;
	private ColumnChart columnChart = null;

	@UiField
	HTMLPanel scoreStats;

	@UiField(provided = true)
	@Path("usersList")
	UserSelectionCellListView usersList;

	public StatsView() {
		MultiSelectionModel<UserProxy> model = new MultiSelectionModel<UserProxy>();
		model.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				if (lineChart != null) {
					scoreStats.remove(lineChart);
				}
				if (columnChart != null) {
					scoreStats.remove(columnChart);
				}
				if (activity.getDatas() != null) {
					computeCharts(usersList.getValue());
				}

			}
		});
		usersList = new UserSelectionCellListView(model);
		provider = new ListDataProvider<UserProxy>();
		provider.addDataDisplay(usersList);
		usersList.setProvider(provider);
		initWidget(uiBinder.createAndBindUi(this));
	}

	public void setPresenter(StatsActivity statsActivity) {
		this.activity = statsActivity;
	}

	private void computeCharts(List<String> users) {
		Map<String, Integer> userToIndex = new HashMap<String, Integer>();
		List<String> allUsers = new ArrayList<String>();
		DataTable data = DataTable.create();
		DataTable dataColumnChart = DataTable.create();
		dataColumnChart.addColumn(ColumnType.STRING, "Joueurs");
		dataColumnChart.addColumn(ColumnType.NUMBER, "Fanny encaissés");
		dataColumnChart.addColumn(ColumnType.NUMBER, "Défaites");
		dataColumnChart.addColumn(ColumnType.NUMBER, "Victoires");
		dataColumnChart.addColumn(ColumnType.NUMBER, "Fanny infligés");

		Map<String, ResultDto> lastResults = new HashMap<String, ResultDto>();

		int j = 1;
		int i = -1;
		data.addColumn(ColumnType.DATE, "Date");
		for (GameDto game : activity.getDatas()) {
			StringBuffer tooltip = new StringBuffer("\n");
			for (String user : game.getWinner()) {
				tooltip.append(user).append(" - ");
			}
			tooltip.delete(tooltip.length() - 3, tooltip.length());
			tooltip.append(" : ").append(game.getScoreWinner()).append("\n");

			for (String user : game.getLooser()) {
				tooltip.append(user).append(" - ");
			}
			tooltip.delete(tooltip.length() - 3, tooltip.length());
			tooltip.append(" : ").append(game.getScoreLooser());

			boolean hasResult = false;
			for (ResultDto result : game.getResults()) {
				if (users == null || users.contains(userToId.get(result.getUser()))) {
					lastResults.put(result.getUser(), result);
					if (!hasResult) {
						hasResult = true;
						i++;
						data.addRow();
						data.setValue(i, 0, game.getDateCreation());
					}
					if (!userToIndex.containsKey(result.getUser())) {
						if (users == null) {
							// First load, get the list of all players which have played at least one game
							allUsers.add(result.getUser());
						}
						data.addColumn(ColumnType.NUMBER, result.getUser());
						userToIndex.put(result.getUser(), j++);
					}
					data.setCell(i, userToIndex.get(result.getUser()), result.getPoints(), result.getPoints() + tooltip.toString(), null);
				}
			}
		}

		if (j == 0) {
			// Add fake column
			data.addColumn(ColumnType.NUMBER, "No data");
		}

		if (users == null) {
			// let's fill the users checkboxs !
			loadUsers(allUsers);
		}

		Options options = Options.create();
		options.setWidth(scoreStats.getOffsetWidth());
		options.setHeight(250);
		options.setTitle("Evolution du score");
		options.setEnableTooltip(true);
		options.setLegend(LegendPosition.BOTTOM);
		options.setSmoothLine(true);
		options.setOption("tooltipWidth", 200);
		options.setOption("tooltipHeight", 200);

		lineChart = new LineChart(data, options);
		scoreStats.add(lineChart);

		i = 0;
		for (ResultDto result : lastResults.values()) {
			dataColumnChart.addRow();
			dataColumnChart.setValue(i, 0, result.getUser());
			dataColumnChart.setValue(i, 1, result.getFannyLooseGames());
			dataColumnChart.setValue(i, 2, result.getLooseGames() - result.getFannyLooseGames());
			dataColumnChart.setValue(i, 3, result.getWinGames() - result.getFannyWinGames());
			dataColumnChart.setValue(i, 4, result.getFannyWinGames());
			i++;
		}

		com.google.gwt.visualization.client.visualizations.ColumnChart.Options optionsColumnChart = com.google.gwt.visualization.client.visualizations.ColumnChart.Options.create();
		optionsColumnChart.setStacked(true);
		optionsColumnChart.setWidth(scoreStats.getOffsetWidth());
		optionsColumnChart.setHeight(250);

		columnChart = new ColumnChart(dataColumnChart, optionsColumnChart);
		scoreStats.add(columnChart);
	}

	public void buildScoreStatsForAll() {
		computeCharts(null);
	}

	private void loadUsers(List<String> users) {
		for (Iterator<UserProxy> it = activity.getUsers().iterator(); it.hasNext();) {
			UserProxy user = it.next();
			if (users.contains(user.getNickname())) {
				userToId.put(user.getNickname(), user.getId());
			} else {
				it.remove();
			}
		}
		provider.setList(activity.getUsers());
		usersList.setValue(new ArrayList<String>(userToId.values()));
	}

}
